home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / Sessions / Traut / ZStrings / Source / CrossPlatform / ZStringDictionary.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-06-23  |  6.2 KB  |  248 lines

  1. /*==================================================================
  2.     File:        ZStringDictionary.cpp
  3.     
  4.     Contains:    Class for parsing named ZStrings into platform-
  5.                 specific strings.
  6.  
  7.     Written by:    Eric Traut
  8.     
  9.     Copyright:    2000-2001 Connectix Corporation
  10.     
  11.     This source has been placed into the public domain by
  12.     Connectix Corporation. You have the right to modify, 
  13.     distribute or use this code without any legal limitations
  14.     or finanicial/licensing requirements. Connectix is not 
  15.     liable for any problems that result from the use of this 
  16.     code.
  17.     
  18.     If you have comments, feedback, questions, or would like
  19.     to submit bug fixes or updates to this code, please email
  20.     opensource@connectix.com.
  21. ==================================================================*/
  22.  
  23. #include "ZStringDictionary.h"
  24. #include "ZString.h"
  25.  
  26. #include <stdlib.h>
  27. #include <new>
  28.  
  29.  
  30. /*==================================================================
  31.     
  32.     Explanation:
  33.     
  34.     This module implements a simple dictionary that associates
  35.     string path names with their values. Each path name is
  36.     delimited by "/" characters.
  37.     
  38.     The class currently assumes that the name string is statically
  39.     allocated and will not go away. We can change this assumption
  40.     in the future if we want to make copies of the string name
  41.     at registration time.
  42.     
  43.     Currently, the dictionary is implemented as a simple hash table.
  44.     In the future, we may want to go with a more complex tree
  45.     structure of some sort that follows the path hierarchy.
  46.     
  47. ==================================================================*/
  48.  
  49.  
  50. ZStringDictionary *            ZStringDictionary::sDictionary = NULL;
  51.  
  52.  
  53. /*------------------------------------------------------------------
  54.     ZStringDictionary
  55. ------------------------------------------------------------------*/
  56.  
  57. ZStringDictionary::ZStringDictionary()
  58. {
  59.     // This is a singleton class
  60.     check(sDictionary == NULL);
  61.     sDictionary = this;
  62.     
  63.     // Zero out the hash table.
  64.     memset(mDictionaryHash, 0, sizeof(mDictionaryHash));
  65. }
  66.  
  67.  
  68. /*------------------------------------------------------------------
  69.     ~ZStringDictionary
  70. ------------------------------------------------------------------*/
  71.  
  72. ZStringDictionary::~ZStringDictionary()
  73. {
  74.     check(sDictionary == this);
  75.     sDictionary = NULL;
  76.     
  77.     // Now, delete all the strings. Their underlying data
  78.     // will go away if their ref counts go to zero after
  79.     // the dictionary stops referring to them.
  80.     Z_UInt32 entryIndex;
  81.     for (entryIndex = 0; entryIndex < kZDictionaryHashEntries; entryIndex++)
  82.     {
  83.         ZDictionaryEntry *    curEntry = mDictionaryHash[entryIndex];
  84.         ZDictionaryEntry *    nextEntry;
  85.         
  86.         while (curEntry != NULL)
  87.         {
  88.             nextEntry = curEntry->mNext;
  89.             
  90.             delete curEntry;
  91.             
  92.             curEntry = nextEntry;
  93.         }
  94.     }
  95. }
  96.  
  97.  
  98. /*------------------------------------------------------------------
  99.     LookUpString
  100. ------------------------------------------------------------------*/
  101.  
  102. Z_Boolean
  103. ZStringDictionary::LookUpString(
  104.     const ZStringParseInfo &    inParseInfo,
  105.     ZString &                    outZString)
  106. {
  107.     Z_UInt32            entryIndex = HashString(inParseInfo.fNameStr, inParseInfo.fNameStrLen);
  108.     ZDictionaryEntry *    curEntry = mDictionaryHash[entryIndex];
  109.     
  110.     while (curEntry != NULL)
  111.     {
  112.         // Do the lengths match?
  113.         if (curEntry->mNameStrLen == inParseInfo.fNameStrLen)
  114.         {
  115.             Z_UInt32 curCharIndex;
  116.             Z_Boolean stringsMatch = true;
  117.  
  118.             for (curCharIndex = 0; curCharIndex < curEntry->mNameStrLen; curCharIndex++)
  119.             {
  120.                 if (curEntry->mNameStr[curCharIndex] != inParseInfo.fNameStr[curCharIndex])
  121.                 {
  122.                     stringsMatch = false;
  123.                     break;
  124.                 }
  125.             }
  126.             
  127.             // Did we find a match? If so, return the string.
  128.             if (stringsMatch)
  129.             {
  130.                 outZString = curEntry->mString;
  131.                 return true;
  132.             }
  133.         }
  134.         
  135.         curEntry = curEntry->mNext;
  136.     }
  137.  
  138.     return false;
  139. }
  140.  
  141.  
  142. /*------------------------------------------------------------------
  143.     RegisterString
  144. ------------------------------------------------------------------*/
  145.  
  146. void
  147. ZStringDictionary::RegisterString(
  148.     const ZStringParseInfo &    inParseInfo,
  149.     ZString &                    inZString)
  150. {
  151.     // The caller should have already verified that
  152.     // the string is not registered already.
  153.  
  154.     ZDictionaryEntry *     newEntry = new (std::nothrow) ZDictionaryEntry(inParseInfo.fNameStr, inParseInfo.fNameStrLen, inParseInfo.fIsVolatile);
  155.     Z_UInt32            entryIndex = HashString(inParseInfo.fNameStr, inParseInfo.fNameStrLen);
  156.  
  157.     if (newEntry != NULL)    // entry was allocated
  158.     {
  159.         if (newEntry->mNameStr == NULL)    // copy of name was not allocated
  160.             { delete newEntry; }
  161.         else                            // copy of name allocated or not needed
  162.         {
  163.             newEntry->mString = inZString;
  164.             newEntry->mNext = mDictionaryHash[entryIndex];
  165.             mDictionaryHash[entryIndex] = newEntry;
  166.         }
  167.     }
  168. }
  169.  
  170.  
  171. /*------------------------------------------------------------------
  172.     HashString
  173. ------------------------------------------------------------------*/
  174.  
  175. Z_UInt32
  176. ZStringDictionary::HashString(
  177.     const char *                inName,
  178.     Z_UInt16                    inNameLen)
  179. {
  180.     Z_UInt16        hashValue = 0;
  181.     Z_UInt16        charsLeft = inNameLen;
  182.     const char *    curChar = inName;
  183.     
  184.     while (charsLeft > 0)
  185.     {
  186.         hashValue <<= 1;
  187.         hashValue += *curChar;
  188.         
  189.         curChar++;
  190.         charsLeft--;
  191.     }
  192.     
  193.     return (hashValue & kZDictionaryEntryMask);
  194. }
  195.  
  196. #pragma mark -
  197.  
  198. /*------------------------------------------------------------------
  199.     ZDictionaryEntry
  200. ------------------------------------------------------------------*/
  201.  
  202. ZDictionaryEntry::ZDictionaryEntry(
  203.     const char *    inNameStr,
  204.     Z_UInt16        inNameStrLen,
  205.     Z_Boolean        inCopyNameData)
  206.     :    mString(),
  207.         mNameStr(inNameStr),
  208.         mNameStrLen(inNameStrLen),
  209.         mDictionaryOwnsNameData(inCopyNameData),
  210.         mNext(NULL)
  211. {
  212.     check(mNameStr != NULL);
  213.     
  214.     // Create copy of name data if necessary
  215.     if (mDictionaryOwnsNameData)
  216.     {
  217.         Z_UInt8 *    nameCopy = new (std::nothrow) Z_UInt8[inNameStrLen];
  218.         if (nameCopy == NULL)    // allocate failed
  219.         {
  220.             mNameStr = NULL;
  221.             mNameStrLen = 0;
  222.         }
  223.         else                    // allocate succeeded
  224.         {
  225.             // Copy the data
  226.             memcpy(nameCopy, inNameStr, inNameStrLen);
  227.             mNameStr = reinterpret_cast<char *>(nameCopy);
  228.             mNameStrLen = inNameStrLen;
  229.         }
  230.     }
  231. }
  232.  
  233.  
  234. /*------------------------------------------------------------------
  235.     ~ZDictionaryEntry
  236. ------------------------------------------------------------------*/
  237.  
  238. ZDictionaryEntry::~ZDictionaryEntry(void)
  239. {
  240.     // Delete copy of name data if necessary
  241.     if (mDictionaryOwnsNameData && mNameStr != NULL)
  242.     {
  243.         delete [] (Z_UInt8 *)mNameStr;
  244.     }
  245. }
  246.  
  247.  
  248.